package xuan.lib;

import java.util.LinkedList;

import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

/**
 * Class used to process Node path of 3DM
 * e.g : /0/0/1
 * 
 * @author xuan
 */

public class Path {
	private LinkedList<Integer> components;	
	
	public Path(Path path){
		components = new LinkedList<Integer>();
		String[] steps = path.toString().split("/"); 
		for(int i=1;i<steps.length;i++){						
			components.addLast(Integer.parseInt(steps[i]));
		}
	}
	
	/**
	 * @param strPath the string express path
	 */
	public Path(String strPath){
		components = new LinkedList<Integer>();
//		setComponents(p);
		String[] steps = strPath.split("/"); 
		for(int i=1;i<steps.length;i++){						
			components.addLast(Integer.parseInt(steps[i]));
		}
	}
	
	/**
	 * @param node any node to find out its location in tree hierarchy
	 */
	public Path(Node node){
		components = new LinkedList<Integer>();
		Node parent = node.getParentNode();
		while(parent.getNodeType()!=Node.DOCUMENT_NODE){
			int index=0;
			NodeList nodeList = parent.getChildNodes();
			
			while(nodeList.item(index)!=node){
				index++;
			}
			
			components.add(0,index);
			node = parent;
			parent = node.getParentNode();
		}
		
		components.add(0,0);
	}

	
	/**
	 * @return the position of node in children sequence of its parent
	 */
	public int getNodeIndex(){
		return components.getLast();
	}

	public LinkedList<Integer> getComponents(){
		return components;
	}
	
	/**
	 * get the node from this path
	 * 
	 * @param root the root of tree hierarchy
	 * @return the node specified by path
	 */
	public Node getNode(Node root){
		if(components.size()==0) return null;
		Node n=root;
		
		for(int i=1;i<components.size();i++){			
			try{
				n = n.getChildNodes().item(components.get(i));
			}
			catch(Exception e){
				return null;
			}
		}	
		return n;		
	}
	
	/**
	 * @return path of parent
	 */
	public Path getParentPath(){
		String path = this.toString(); 
		path = path.substring(0,path.lastIndexOf('/'));
		return new Path(path);
	}
	
	public int getAComponent(int depth){//0 : root
		return components.get(depth);
	}

	/**
	 * @param p path points to another node
	 * @return true if current node is child of another node
	 */
	public boolean isChildOf(Path p) {
		if(p==null || Depth() != p.Depth()+1) return false;
		for(int i=1;i <= p.Depth();i++){
			if(components.get(i) != p.getAComponent(i)) return false;
		}
		return true;
	}

	/**
	 * @param p path points to another node
	 * @return true if current node is descendant of another node
	 */
	public boolean isDescendantOf(Path p){		
		if(p==null || Depth()<= p.Depth()) return false;
		for(int i=1;i <= p.Depth();i++){
			if(components.get(i) != p.getAComponent(i)) return false;
		}
		return true;
	}
	
	/**
	 * @param p path points to another node
	 * @return true if current node is right of another node
	 */
	public boolean isRightOf(Path p) {
		for(int i=1;i <= Math.min(p.Depth(),Depth());i++){
			if(components.get(i) > p.getAComponent(i)) return true;
		}
		return false;
	}

	/**
	 * @return depth of path
	 */
	public int Depth(){
		return (components.size()-1);
	}

	public boolean equals(Path pth){
		return (toString().compareTo(pth.toString())==0)?true:false;
	}

	public String toString(){
		String pS="";
		for(int i=0;i<components.size();i++){
			pS = pS + "/" + String.valueOf(components.get(i));
		}
		return pS;
	}
}
